home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / BITMAP.ZIP / ICNFILE.C < prev    next >
C/C++ Source or Header  |  1993-04-19  |  7KB  |  275 lines

  1. /*
  2. **    $id: ssvcid icnfile.c 1.0 10/15/91  9:49 am$
  3. **        This file contains the code needed to read in a Windows icon file
  4. **    and generate a valid icon from it.
  5. **
  6. **    (C) 1991-3    Larry Widing
  7. */
  8. #include    <windows.h>
  9. #include    <malloc.h>
  10. #include    <memory.h>
  11. #include    "bitmaps.h"
  12. #include    "icnfile.h"
  13.  
  14. /*
  15. **    Global variables - used for InfoDisplay()
  16. */
  17. ICONDATA            CurIcon;
  18. ICONFILEHEADER    CurIconFile;
  19.  
  20. /*
  21. ** HICON                                            handle of created icon
  22. ** ReadIconFile(const char *filename);    name of file to load
  23. **
  24. **    This function will read the passed file in, and create a icon
  25. **    whose handle will be returned to the caller.
  26. **
  27. ** Modification History:
  28. ** 09/06/91  LCW  Created
  29. */
  30. HICON
  31. ReadIconFile(const char *filename)
  32. {
  33.     int                file;
  34.     int                i, j;
  35.     int                offset;
  36.     int                rc;
  37.     HICON                hicon = (HICON)NULL;
  38.     HDC                hdc;
  39.     int                iconx, icony, ncolors;
  40.     OFSTRUCT            reopen;
  41.     ICONFILEHEADER    header;
  42.     ICONDATA            icon, best;
  43.     char                *buffer;
  44.     BITMAPINFO        *bmi;
  45.     char                *cp, *cp2;
  46.     char                mask[512];
  47.     char                *iconDIB;
  48.  
  49.     /*
  50.     **    Get some system values
  51.     */
  52.     hdc = GetDC(MainWindow);
  53.     if (hdc == (HDC)NULL)
  54.     {
  55.         ErrorBox("ReadIconFile(): Unable to get a device context");
  56.         return (HICON)NULL;
  57.     }
  58.     iconx = GetSystemMetrics(SM_CXICON);
  59.     icony = GetSystemMetrics(SM_CYICON);
  60.     ncolors = GetDeviceCaps(hdc, NUMCOLORS);
  61.     ReleaseDC(MainWindow, hdc);
  62.  
  63.     /*
  64.     **    Allocate some needed buffers
  65.     */
  66.     buffer = malloc(4712);
  67.     if (buffer == NULL)
  68.     {
  69.         ErrorBox("ReadIconFile(): Unable to allocate memory for icon buffer");
  70.         return (HICON)NULL;
  71.     }
  72.     bmi = (BITMAPINFO *)buffer;
  73.     iconDIB = malloc(4096);
  74.     if (iconDIB == NULL)
  75.     {
  76.         ErrorBox("ReadIconFile(): Unable to allocate memory for icon DIB");
  77.         free(buffer);
  78.         return (HICON)NULL;
  79.     }
  80.  
  81.     file = OpenFile((LPSTR)filename, (LPOFSTRUCT)&reopen, OF_READ | OF_SHARE_DENY_NONE);
  82.  
  83.     if (file >= 0)
  84.     {
  85.         /*
  86.         ** Read in Icon File header
  87.         */
  88.         rc = _lread(file, (char far *)&header, sizeof(header));
  89.         if (rc == sizeof(header) && header.icoReserved == 0
  90.             && header.icoResourceType == 1)
  91.         {
  92.             if (header.icoResourceCount != 0)
  93.             {
  94.                 /*
  95.                 ** Look for the correct Icon by scanning through the directory for
  96.                 ** an extact match.
  97.                 */
  98.                 memset(&best, 0, sizeof(best));
  99.  
  100.                 for (i = rc = 0 ; rc >= 0 && i < header.icoResourceCount ; ++i)
  101.                 {
  102.                     rc = _lread(file, (char far *)&icon, sizeof(ICONDATA));
  103.                     if (rc == sizeof(ICONDATA))
  104.                     {
  105.                         if (icon.width == iconx && icon.height == icony)
  106.                         {
  107.                             if (icon.colorCount == ncolors)
  108.                             {
  109.                                 best = icon;
  110.                                 break;
  111.                             }
  112.                             else if (icon.colorCount > best.colorCount)
  113.                             {
  114.                                 if (icon.colorCount < ncolors)
  115.                                     best = icon;
  116.                             }
  117.                             else
  118.                             {
  119.                                 if (icon.colorCount > ncolors)
  120.                                     best = icon;
  121.                             }
  122.                         }
  123.                     }
  124.                     else
  125.                     {
  126.                         ErrorBox("ReadIconFile(): Error reading icon directory");
  127.                         rc = -1;
  128.                     }
  129.                 }
  130.  
  131.                 if (rc >= 0)
  132.                 {
  133.                     if (best.width != 0)
  134.                     {
  135.                         _llseek(file, best.icoDIBOffset, 0);
  136.                         rc = _lread(file, (LPSTR)buffer, (int)best.icoDIBSize);
  137.                         if (rc == (int)best.icoDIBSize)
  138.                         {
  139.                             offset = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * (best.colorCount - 1);
  140.                             bmi->bmiHeader.biSizeImage -= best.width * best.height / 8;
  141.  
  142.                             if (bmi->bmiHeader.biBitCount == 1)
  143.                             {
  144.                                 /*
  145.                                 ** Invert Icon image - only if monochrome
  146.                                 **        rc  == line width in bytes
  147.                                 **        cp  == pointer to DIB from file
  148.                                 **        cp2 == pointer to proper line in iconDIB
  149.                                 */
  150.                                 rc = best.width / 8 * bmi->bmiHeader.biPlanes
  151.                                     * bmi->bmiHeader.biBitCount;
  152.                                 cp = buffer + offset;
  153.                                 cp2 = iconDIB + (best.height - 1) * rc;
  154.  
  155.                                 for (j = 0 ; j < best.height ; ++j)
  156.                                 {
  157.                                     memcpy(cp2, cp, rc);
  158.                                     cp += rc;
  159.                                     cp2 -= rc;
  160.                                 }
  161.                             }
  162.  
  163.                             /*
  164.                             ** Invert Icon mask
  165.                             **        rc  == line width in bytes
  166.                             **        cp  == pointer to mask DIB from file
  167.                             **        cp2 == pointer to proper line in mask
  168.                             */
  169.                             rc = best.width / 8;
  170.                             cp = buffer + offset + (int)bmi->bmiHeader.biSizeImage;
  171.                             cp2 = mask + (best.height - 1) * rc;
  172.  
  173.                             for (j = 0 ; j < best.height ; ++j)
  174.                             {
  175.                                 memcpy(cp2, cp, rc);
  176.                                 cp += rc;
  177.                                 cp2 -= rc;
  178.                             }
  179.  
  180.                             if (bmi->bmiHeader.biBitCount > 1)
  181.                             {
  182.                                 HBITMAP    hbm;
  183.                                 BITMAP    bm;
  184.  
  185.                                 /*
  186.                                 **    Create the DIB portion of the bitmap
  187.                                 */
  188.                                 bmi->bmiHeader.biHeight = best.height;
  189.                                 bmi->bmiHeader.biWidth = best.width;
  190.  
  191.                                 hbm = CreateDIBitmap(hdc, (BITMAPINFOHEADER FAR *)bmi,
  192.                                     CBM_INIT, (LPSTR)buffer + offset,
  193.                                     (BITMAPINFO FAR *)bmi, DIB_RGB_COLORS);
  194.  
  195.                                 if (hbm != (HBITMAP)NULL)
  196.                                 {
  197.                                     if (GetObject(hbm, sizeof(bm), (LPSTR)&bm)
  198.                                         == sizeof(bm))
  199.                                     {
  200.                                         rc = bm.bmWidthBytes * bm.bmPlanes * bm.bmHeight;
  201.                                         if (GetBitmapBits(hbm, rc, (LPSTR)iconDIB) == rc)
  202.                                         {
  203.                                             bmi->bmiHeader.biPlanes = bm.bmPlanes;
  204.                                             bmi->bmiHeader.biBitCount = bm.bmBitsPixel;
  205.                                         }
  206.                                         else
  207.                                         {
  208.                                             ErrorBox("ReadIconFile(): Error getting bitmap bits");
  209.                                         }
  210.                                     }
  211.                                     else
  212.                                     {
  213.                                         ErrorBox("ReadIconFile(): Error getting bitmap data");
  214.                                     }
  215.                                     DeleteObject(hbm);
  216.                                 }
  217.                                 else
  218.                                 {
  219.                                     ErrorBox("ReadIconFile(): Error creating bitmap");
  220.                                 }
  221.                             }
  222.  
  223.                             /*
  224.                             **    Now to create the icon
  225.                             */
  226.                             hicon = CreateIcon(AppInstance, best.width, best.height,
  227.                                 bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount,
  228.                                 (LPSTR)mask, (LPSTR)iconDIB);
  229.  
  230.                             if (hicon != (HICON)NULL)
  231.                             {
  232.                                 CurIcon = best;
  233.                                 CurIconFile = header;
  234.                             }
  235.                         }
  236.                         else
  237.                         {
  238.                             ErrorBox("ReadIconFile(): Error reading icon data");
  239.                         }
  240.                     }
  241.                 }
  242.             }
  243.             else
  244.             {
  245.                 ErrorBox("ReadIconFile(): Error Icon Count is 0");
  246.             }
  247.         }
  248.         else
  249.         {
  250.             ErrorBox("ReadIconFile(): Error Reading Icon Header");
  251.         }
  252.         _lclose(file);
  253.     }
  254.     else
  255.     {
  256.         ErrorBox("ReadIconFile(): Error Opening Icon File");
  257.     }
  258.  
  259.     /*
  260.     **    Free up allocated memory
  261.     */
  262.     free(buffer);
  263.     free(iconDIB);
  264.  
  265.     return hicon;
  266. }
  267.  
  268. /*
  269. **    Modification History
  270. **    --------------------
  271. **    $lgb$
  272. ** 10/15/91     Larry Widing   Initial version for Win Tech Journal Article.
  273. **    $lge$
  274. */
  275.